package com.github.zxhTom.rabbitmqservice;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.ContentTypeDelegatingMessageConverter;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;


/**
 * @author zxh
 */
@Configuration
public class RabbitConfig {

    /**
     * 直连类型交换机
     */
    public static final String DIRECTEXCHANGE = "direct";
    /**
     * topic类型交换机
     */
    public static final String TOPICEXCHANGE = "topic";
    /**
     * 头类型交换机
     */
    public static final String HEADEXCHANGE = "head";
    /**
     * 广播类型交换机
     */
    public static final String FANOUTEXCHANGE = "fanout";

    /******************************************************************/

    public static final String QUEUEFIRST = "test1";
    public static final String QUEUESECOND = "test2";
    public static final String QUEUETHIRD = "test3";
    public static final String QUEUEFORTH = "test4";
    public static final String QUEUEDEAD = "dead";
    public static final String KEYFIRST = "test1";
    public static final String KEYSECOND = "test1";
    public static final String KEYTHIRD = "test1";
    public static final String DIRECTIONKEY = "directionKey";

    @Bean
    public Queue queue1() {
        return new Queue(QUEUEFIRST,true);
    }
    @Bean
    public Queue queue2() {
        return new Queue(QUEUESECOND,true);
    }
    @Bean
    public Queue queue3() {
        return new Queue(QUEUETHIRD,true);
    }
    @Bean
    public Queue queue4() {
        return new Queue(QUEUEFORTH,true);
    }
    @Bean
    public Queue deadLetterQueue(){
        Map<String, Object> arguments = new HashMap<String, Object>();
        //设置此死信队列消息过期后，消息转发到那个队列上
        arguments.put("x-dead-letter-exchange", DIRECTEXCHANGE);
        arguments.put("x-dead-letter-routing-key", DIRECTIONKEY);
        return new Queue(QUEUEDEAD, true, false, false,arguments);
    }

    @Bean
    public DirectExchange directExchange(){
        return new DirectExchange(DIRECTEXCHANGE,true,false);
    }
    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange(TOPICEXCHANGE,true,false);
    }
    @Bean
    public HeadersExchange headersExchange(){
        return new HeadersExchange(HEADEXCHANGE,true,false);
    }
    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange(FANOUTEXCHANGE,true,false);
    }

    /**
     * directionExchange() 与  queue1() 绑定在一起 ， key 是directionKey
     * 这个key是自定义的，不一定和queue的名称相同,
     * DirectExchange是RabbitMQ的默认交换机，直接使用routingKey匹配队列
     * 换句话说我们发送消息的时候可以用发送到交换机，也可以直接发送给队列
     * @return
     */
    @Bean
    public Binding binding1(){
        return BindingBuilder.bind(queue1()).to(directExchange()).with(DIRECTIONKEY);
    }

    /**
     * topic绑定的key 按. 进行单词的区分 ; # 表示多个单词  * 表示1个单词
     * zxh.#  ： 匹配zxh开头的任何形式单词 zxh ; zxh.test.test; zxh.demo  这些都能匹配
     * zxh.*  :  配置zxh ; zxh.test ; zxh.demo都能匹配
     * @return
     */
    @Bean
    public Binding topicBinding1(){
        return BindingBuilder.bind(queue1()).to(topicExchange()).with("zxh.#");
    }
    @Bean
    public Binding topicBinding2(){
        return BindingBuilder.bind(queue2()).to(topicExchange()).with("zxh.test");
    }

    /**
     * 请求数据中必须符合headerValues中任意一个参数
     * @return
     */
    @Bean
    public Binding headBinding1(){
        Map<String,Object> headerValues = new HashMap<>();
        headerValues.put("type", "cash");
        headerValues.put("aging", "fast");
        return BindingBuilder.bind(queue1()).to(headersExchange()).whereAll(headerValues).match();
    }

    /**
     * 请求数据中必须符合headerValues中任意一个参数
     * @return
     */
    @Bean
    public Binding headBinding2(){
        Map<String,Object> headerValues = new HashMap<>();
        headerValues.put("type", "cash");
        headerValues.put("aging", "fast");
        return BindingBuilder.bind(queue3()).to(headersExchange()).whereAny(headerValues).match();
    }

    @Bean
    public Binding fanoutBinding1(){
        return BindingBuilder.bind(queue1()).to(fanoutExchange());
    }
    @Bean
    public Binding fanoutBinding2(){
        return BindingBuilder.bind(queue2()).to(fanoutExchange());
    }
    @Bean
    public Binding fanoutBinding3(){
        return BindingBuilder.bind(queue3()).to(fanoutExchange());
    }
    @Bean
    public Binding fanoutBinding4(){
        return BindingBuilder.bind(queue4()).to(fanoutExchange());
    }
    @Bean
    public Binding deadBinding(){
        return BindingBuilder.bind(deadLetterQueue()).to(directExchange()).with(QUEUEDEAD);
    }
    @Bean
    public RabbitAdmin rabbitTemplate(ConnectionFactory connectionFactory) {
        return new RabbitAdmin(connectionFactory);
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(messageConverter);
        return template;
    }

    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory, MessageConverter messageConverter) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(messageConverter);
        return factory;
    }

    @Bean
    public MessageConverter messageConverter() {
        return new ContentTypeDelegatingMessageConverter(new Jackson2JsonMessageConverter());
    }

}
